package com.putable.nmc.dmv.tests;

import java.io.StringWriter;

import junit.framework.TestCase;

import com.putable.nmc.dmv.Customer;
import com.putable.nmc.dmv.CustomerLine;
import com.putable.nmc.dmv.CustomerState;
import com.putable.nmc.dmv.Door;
import com.putable.nmc.world.CIT;
import com.putable.nmc.world.World;
import com.putable.pqueue.PQueue;
import com.putable.pqueue.PQueueImpl;

public class TestCustomer extends TestCase {
	
	public void testOneCustomer(){
		World world = new World();
		double time = 0; 
		CIT cit = world.getNextCIT(time);
		PQueue pq = new PQueueImpl();
		CustomerLine cLine = new CustomerLine();
		Door door = new Door(pq);
		
		Customer c = new Customer(pq, cit, world);
		
		door.addCustToPQ(time, c);
		double nextTime = cit.getArrivalTime();
		c = (Customer) pq.remove();
		time = c.getTimeOfNextTask();
		assertEquals(nextTime, time);//makes sure the customer arrives at the right time
		assertEquals(CustomerState.ARRIVED, c.getState());
		c.run(time, cLine);
		
		assertFalse(cLine.isEmpty());
		
		nextTime = cit.getGiveupTime() + cit.getArrivalTime();
		c = (Customer) pq.remove();
		time = c.getTimeOfNextTask();
		assertEquals(nextTime, time);//make sure the customer leaves at the right time
		time = c.getTimeOfNextTask();
		assertEquals(CustomerState.WAITING, c.getState());
		c.run(time, cLine);

		//writeScore(world);
	}
	
	public void testWaitingInLine(){
		World world = new World();
		double time = 0; 
		PQueue pq = new PQueueImpl();
		CustomerLine cLine = new CustomerLine();
		Door door = new Door(pq);
		while(true){
			CIT cit = world.getNextCIT(time);
			Customer c = new Customer(pq, cit, world);
			
			door.addCustToPQ(time, c);//Add customer to queue 
			
			c = (Customer) pq.remove();
			time = c.getTimeOfNextTask();
			assertEquals(CustomerState.ARRIVED, c.getState());
			c.run(time, cLine);
			
			
			c = (Customer) pq.remove();
			time = c.getTimeOfNextTask();
			assertEquals(CustomerState.WAITING, c.getState());
			c.run(time, cLine);
			if(time >= 36000) break;
		}
		//writeScore(world);
	}
	
	public void testTransactions(){
		World world = new World();
		double time = 0; 
		PQueue pq = new PQueueImpl();
		CustomerLine cLine = new CustomerLine();
		Door door = new Door(pq);
		while(true){
			CIT cit = world.getNextCIT(time);
			Customer c = new Customer(pq, cit, world);
			
			door.addCustToPQ(time, c);
			c = (Customer) pq.remove();
			time = c.getTimeOfNextTask();
			c.run(time, cLine);
			pq.delete(c);
			cLine.delete(c, time);
			c.setState(CustomerState.TRANSACTING);
			c.run(time, cLine);
			
			
			if(time > 36000)break;
		}
		writeScore(world);
	}


	public void writeScore(World world){
		StringWriter writer = new StringWriter();
		world.getScore(writer);
		System.out.println(writer.toString());
	}
}
